package gov.pbc.nn.kjgl.xkyyh.view;

import gov.pbc.nn.kjgl.Constants;
import gov.pbc.nn.kjgl.archive.dao.ArchivesInputDao;
import gov.pbc.nn.kjgl.entity.Archives;
import gov.pbc.nn.kjgl.entity.ProjectFile;
import gov.pbc.nn.kjgl.entity.WorkPlan;
import gov.pbc.nn.kjgl.item.template.entity.AcceptDept;
import gov.pbc.nn.kjgl.task.entity.TaskBranchUser;
import gov.pbc.nn.kjgl.task.entity.TaskEntity;
import gov.pbc.nn.kjgl.task.entity.TaskProcessor;
import gov.pbc.nn.kjgl.xkyyh.dao.NewBankDao;
import gov.pbc.nn.kjgl.xkyyh.entity.BackTrain;
import gov.pbc.nn.kjgl.xkyyh.entity.NewBank;
import gov.pbc.nn.kjgl.xkyyh.entity.TrainDept;
import gov.pbc.nn.uflo.UfloUtils;
import gov.pbc.nn.uflo.entity.Opinion;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.annotation.Resource;

import gov.pbc.nn.core.bdf.entity.Dept;
import gov.pbc.nn.core.bdf.service.UserService.DefaultUserRowMapper;
import gov.pbc.nn.core.dao.CommonJdbcDao;
import gov.pbc.nn.core.dao.PbcnnCoreHibernateDao;
import gov.pbc.nn.core.dao.PbcnnCoreJdbcDao;
import gov.pbc.nn.core.entity.BaseEntity;
import gov.pbc.nn.core.utils.EntityRowMapperUtils;
import gov.pbc.nn.core.utils.GetTableUtils;
import gov.pbc.nn.core.utils.SecurityUtils;
import org.apache.commons.lang.StringUtils;
import org.h2.util.New;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import com.bstek.bdf2.core.business.IUser;
import com.bstek.bdf2.core.context.ContextHolder;
import com.bstek.bdf2.core.orm.ParseResult;
import com.bstek.bdf2.core.orm.hibernate.ISessionCallback;
import com.bstek.dorado.annotation.DataProvider;
import com.bstek.dorado.annotation.DataResolver;
import com.bstek.dorado.annotation.Expose;
import com.bstek.dorado.core.Configure;
import com.bstek.dorado.data.entity.EntityState;
import com.bstek.dorado.data.entity.EntityUtils;
import com.bstek.dorado.data.provider.Criteria;
import com.bstek.dorado.data.provider.Page;
import com.bstek.dorado.data.variant.Record;
import com.bstek.dorado.uploader.DownloadFile;
import com.bstek.dorado.uploader.UploadFile;
import com.bstek.dorado.uploader.annotation.FileProvider;
import com.bstek.dorado.uploader.annotation.FileResolver;
import com.bstek.uflo.client.service.ProcessClient;
import com.bstek.uflo.client.service.TaskClient;
import com.bstek.uflo.designer.utils.EscapeUtils;
import com.bstek.uflo.model.ProcessInstance;
import com.bstek.uflo.model.task.Task;
import com.bstek.uflo.query.ProcessInstanceQuery;
import com.bstek.uflo.service.ProcessService;
import com.bstek.uflo.service.StartProcessInfo;
import com.bstek.uflo.service.TaskService;

@Component("newBankPR")
public class NewBankPR {

	@Autowired
	private NewBankDao bankDao;
	

	@Resource(name = PbcnnCoreHibernateDao.BEAN_ID)
	private PbcnnCoreHibernateDao coreHibernateDao;

	@Resource(name = CommonJdbcDao.BEAN_ID)
	private CommonJdbcDao commonJdbcDao;
	
	@Autowired
	@Qualifier(ProcessClient.BEAN_ID)
	private ProcessClient processClient;
	
	@Autowired
	@Qualifier(TaskClient.BEAN_ID)
	private TaskClient tc;

	@Autowired
	@Qualifier(TaskService.BEAN_ID)
	private TaskService taskService;

	@Autowired
	@Qualifier(ProcessService.BEAN_ID)
	private ProcessService processService;
	
	@Resource(name = ProcessClient.BEAN_ID)
	private ProcessClient pc;

	public class BankRowMapper implements RowMapper<NewBank>{
		@Override
		public NewBank mapRow(ResultSet rs, int rowNum) throws SQLException {
			return EntityRowMapperUtils.get(NewBank.class, rs, rowNum);
		}		
	}
	
	public class TrainDeptMapper implements RowMapper<TrainDept>{
		@Override
		public TrainDept mapRow(ResultSet rs, int rowNum) throws SQLException {
			return EntityRowMapperUtils.get(TrainDept.class, rs, rowNum);
		}		
	}
	
	public class BackTrainMapper implements RowMapper<BackTrain>{
		@Override
		public BackTrain mapRow(ResultSet rs, int rowNum) throws SQLException {
			return EntityRowMapperUtils.get(BackTrain.class, rs, rowNum);
		}		
	}
	
	@DataProvider
	public NewBank loadNewBank(String id) throws Exception {
		if (StringUtils.isEmpty(id)) {
			return null;
		}
		NewBank newBankEntity = (NewBank) this.bankDao.get(
				 id,NewBank.class);	
		return newBankEntity;
	}	
	
	@DataProvider
	public List<TrainDept> loadTrainDepts(String id) throws Exception{
		String sql = "SELECT\n"
				+ "			D.* \n"
				+ "		FROM\n"
				+ "			t_train_dept D\n"
				+"WHERE\n" 
				+"	D.INVALID_=0 and D.BANK_ID_=?";
		return this.commonJdbcDao.getJdbcTemplate().query(sql, new Object[] { id },new TrainDeptMapper());	
	}
	
	@DataProvider
	public List<BackTrain> loadBackTrains(String id) throws Exception {
		String sql = "SELECT\n"
				+ "			BT.* \n"
				+ "		FROM\n"
				+ "			t_back_train BT\n"
				+"WHERE\n" 
				+"	BT.INVALID_=0 and BT.TRAIN_ID_=?";
		return this.commonJdbcDao.getJdbcTemplate().query(sql, new Object[] { id },new BackTrainMapper());	
	}
	
	@DataProvider
	public TrainDept loadTrainDeptByLoginUser(String newBankId) throws Exception {	
		String deptId=((Dept)ContextHolder.getLoginUser().getDepts().get(0)).getCDept().getId();
		String sql = "SELECT\n"
				+ "			D.* \n"
				+ "		FROM\n"
				+ "			t_train_dept D\n"
				+"WHERE\n" 
				+"	D.INVALID_=0 and D.DEPT_ID_ = ? and D.BANK_ID_=?";
		List<TrainDept> trainDepts=	this.commonJdbcDao.getJdbcTemplate().query(sql, new Object[] { deptId, newBankId },new TrainDeptMapper());		
		if(trainDepts!=null&&trainDepts.size()>0)
			return trainDepts.get(0);
		else return null;
	}
	
	@DataProvider
	public  List<IUser> getdeptUsers()
	{
		 try {
			 String sql="select u.* from T_USER u,bdf2_user_dept ud where u.USERNAME_=ud.USERNAME_ and ud.DEPT_ID_ like ?";
			 PbcnnCoreJdbcDao jdbc = ContextHolder.getBean(PbcnnCoreJdbcDao.BEAN_ID);
			 List<IUser> users = jdbc.getJdbcTemplate().query(sql,
						new Object[] { ContextHolder.getLoginUser().getDepts().get(0).getId()+"%" }, new DefaultUserRowMapper());
			 return users;
		} catch (Exception e) {
			e.printStackTrace();
			return new ArrayList<IUser>();
			// TODO: handle exception
		}
	}
	
	@DataProvider
	public void getNewBankPage(Page<NewBank> page, Criteria criteria) throws Exception{
		String sql = "SELECT\n"
				+ "			B.* \n"
				+ "		FROM\n"
				+ "			t_new_bank B\n"
				+"WHERE\n" 
				+"	B.INVALID_=0 ";
//		if(!this.commonJdbcDao.containsProperty("state", criteria)){
//			sql += "  and b.state_ in (0,10) ";
//		}
		ParseResult result = this.commonJdbcDao.parseCriteria(criteria, true, "B");
		if (result != null) {
			StringBuffer sb = result.getAssemblySql();
			Map<String, Object> valueMap = result.getValueMap();
			sql += " and "+sb.toString() +" order by B.CREATE_DATE_,B.UPDATE_DATE_ ";
			this.commonJdbcDao.pagingQuery(page, sql,new BankRowMapper(),valueMap);
		} else {
			sql +=" order by B.CREATE_DATE_,B.UPDATE_DATE_ ";
			this.commonJdbcDao.pagingQuery(page,  sql,new BankRowMapper());
		}
	}
	
	@DataProvider
	public void getNewBankPagebyDept(Page<NewBank> page, Criteria criteria) throws Exception {		
		String deptId=((Dept)ContextHolder.getLoginUser().getDepts().get(0)).getCDept().getId();
		String sql = "SELECT\n"
				+ "			B.* \n"
				+ "		FROM\n"
				+ "			t_new_bank B\n"
				+ "		LEFT JOIN t_train_dept D ON B.ID_ = D.BANK_ID_\n"
				+"WHERE\n" 
				+"	B.INVALID_=0 and D.INVALID_=0 and D.DEPT_ID_ = :deptId ";
		if(!this.commonJdbcDao.containsProperty("state", criteria)){
			sql += "  and b.state_=30 ";
		}
		ParseResult result = this.commonJdbcDao.parseCriteria(criteria, true, "B");
		if (result != null) {
			StringBuffer sb = result.getAssemblySql();
			Map<String, Object> valueMap = result.getValueMap();
			valueMap.put("deptId", deptId);
			sql += " and "+sb.toString() +" order by B.CREATE_DATE_,B.UPDATE_DATE_ ";
			this.commonJdbcDao.pagingQuery(page, sql,new BankRowMapper(),valueMap);
		} else {
			Map<String,Object> parameter = new HashMap<String,Object>();
			parameter.put("deptId", deptId);
			sql +=" order by B.CREATE_DATE_,B.UPDATE_DATE_ ";
			this.commonJdbcDao.pagingQuery(page,  sql,new BankRowMapper(),parameter);
		}
	}
	
	@Transactional
	@DataResolver
	private void saveEntity(BaseEntity entity) throws Exception{
		EntityState state=EntityUtils.getState(entity);
		if(state.equals(EntityState.NEW)){
			this.bankDao.save(entity);
		}
		else if(state.equals(EntityState.MODIFIED)){
			this.bankDao.update(entity);
		}
		else if(state.equals(EntityState.DELETED)){
			this.bankDao.delete(entity);
		}
	}
	
	@DataProvider
	public String getTrainDeptOpinionstr(Map<String, Object> params)throws Exception{
		String newBankId = (String) params.get("newBankId");
		String trainCz = (String) params.get("trainCz");
		if(StringUtils.isEmpty(trainCz))
			return "";
		List<String> users=new ArrayList<String>();
		users.add(trainCz);		
		List<Opinion> opinions=UfloUtils.getOpinions(null, newBankId, "辅导参报", null, users);
		if(opinions!=null&&opinions.size()>0)
			return opinions.get(0).getOpinion();
		else return "";
	}
	
	@Expose
	public String checkdept(List<Record> depts) throws Exception{
		for (Record dept : depts) {
			if (dept.getString("id").startsWith(Dept.NANNING) == false||StringUtils.isNotBlank(dept.getString("deptLevel"))) {
				return dept.getString("name") + ",不属于南宁中支的部门,请重新选择!";
			} else {
				List<IUser> users = SecurityUtils.getUserByRoleForDept(dept.getString("id"), Constants.ROLE_CZ);
				if (users.size() <= 0)
					return dept.getString("name") + "，未设置处长，请重新选择!";
			}
		}
		return null;
	}
	
	@DataResolver
	@Transactional
	public void updateNewBank(NewBank newBankEntity) throws Exception{
		NewBank bank=EntityUtils.toEntity(newBankEntity);
		this.saveEntity(bank);
		List<TrainDept> depts=EntityUtils.getValue(bank, "acceptDepts");
		if(depts!=null)
		{
			for (TrainDept dept : depts) {
				dept.setBankId(newBankEntity.getId());
				this.saveEntity(dept);
			}
		}
	}
	
	@DataResolver
	@Transactional
	public void updateBackTrain (BackTrain backTrain) throws Exception{
		this.saveEntity(backTrain);
	}
	
	@Transactional
	@DataResolver
	public void updateFDCB(NewBank newBank) throws Exception {
		NewBank newBankEntity = EntityUtils.toEntity(newBank);
		TrainDept trainDept = EntityUtils.getValue(newBankEntity, "acceptDept");
		List<BackTrain> backTrains = EntityUtils.getValue(trainDept, "backTrains");
		if(backTrains==null)
			return;
		for (BackTrain backTrain : backTrains) {
			backTrain.setTrainId(trainDept.getId());
			this.saveEntity(backTrain);
		}
	}
	
	@DataProvider
	public Collection<Opinion>  getOpinions(String newBankId)throws Exception{
		return UfloUtils.getOpinions(null, newBankId, null,null, null);
	}
	
	@Expose
	public String getLoginUserDeptName()throws Exception{
		return ContextHolder.getLoginUser().getDepts().get(0).getName();
	}
	
	@Expose
	public String checkRole()throws Exception{
		if(ContextHolder.getLoginUser().getDepts().get(0).getId().equals("489145101014")==false)
		{
			return "您的部门不是金融稳定处，无法操作！";
		}
		else if(SecurityUtils.containsRole(ContextHolder.getLoginUserName(), Constants.ROLE_XKYYHGLY)==false){
			return "需要“"+Constants.ROLE_XKYYHGLY+"”角色才能操作！";
		}
		else return "";
	}
	
	@DataProvider
	public Collection<IUser> getCzs() throws Exception {
		return SecurityUtils.getUserByRoleForDept(
				((Dept) ContextHolder.getLoginUser().getDepts().get(0)).getCDept().getId(), Constants.ROLE_CZ);
	}
	
		
		@FileResolver
		@DataResolver
		public Map<String, String> process1(UploadFile file,
				Map<String, Object> parameter) throws Exception {
			//String param1 = (String) parameter.get("param1");// 获取UploadAction的parameter对应的参数值
			//String param2 = (String) parameter.get("param2");// 获取UploadAction的parameter对应的参数值
			//Integer id= (Integer)parameter.get("id");
			
			//String fileId = (String)parameter.get("fileId");
			String filename=file.getFileName();
			String filesavename=UUID.randomUUID().toString();
			Path path=Paths.get(Configure.getString("NEW_BANK_FILE_UPLOAD_PATH"), "");
			Files.createDirectories(path);
			path=path.resolve(filesavename);
			File destFile = Files.createFile(path).toFile();
			file.transferTo(destFile);
			Map<String, String> data = new HashMap<String, String>();
			data.put("fileName", filename);
			data.put("path", destFile.getAbsolutePath());
			//data.put("fileId", fileId);
			return data;
		}
		
		@FileProvider
		public DownloadFile download(Map<String, Object> parameter)throws Exception{
			String fileName =EscapeUtils.unescape((String)parameter.get("fileName"));
			String path = EscapeUtils.unescape((String)parameter.get("path"));
			DownloadFile df=new DownloadFile(new File(path));//返回一个文件对象就可以
			df.setFileName(fileName);
			df.setName( fileName);
			return df;
		}

		@Transactional
		@DataResolver
		@Expose
		public void deleteNewBank(NewBank newBankEntity) throws Exception{
			if(StringUtils.isNotEmpty(newBankEntity.getPath()))
			Files.delete(Paths.get(newBankEntity.getPath()));
			this.bankDao.delete(newBankEntity);
		}
		
		@Transactional
		@DataResolver
		private void completeTask(String newBankId,String taskId,String opinion,Map<String, Object> variables){
			long ltaskId = Long.parseLong(taskId);
			Task task = this.tc.getTask(ltaskId);
			if(variables!=null)
			this.pc.saveProcessVariables(task.getProcessInstanceId(), variables);
			final Opinion o = new Opinion();
			o.setBusKey(newBankId);
			o.setBusTable(GetTableUtils.getTablename(NewBank.class));
			o.setOpinion(opinion);
			o.setProcessInstanceId(task.getProcessInstanceId());
			o.setProcessName("新开业银行辅导");
			o.setTaskId(ltaskId);
			o.setNodeName(task.getNodeName());
			o.setTaskName(task.getTaskName());
			o.setUsername(ContextHolder.getLoginUserName());
			o.setCname(ContextHolder.getLoginUser().getCname());
			o.setDeptId(ContextHolder.getLoginUser().getDepts().get(0).getId());
			o.setDeptName(ContextHolder.getLoginUser().getDepts().get(0).getName());
			this.coreHibernateDao.save(o);		
			this.tc.start(ltaskId);
			this.tc.complete(ltaskId);
		}
		
		@Expose
		@Transactional
		public void startProcess(Map<String, Object> params) throws Exception {
			String newBankId = (String) params.get("newBankId");
			String taskId = (String) params.get("taskId");
			if (StringUtils.isNotEmpty(taskId)) {
				this.completeTask(newBankId, taskId, "修改后重新提交申请", params);			
			} else {	
				StartProcessInfo spi = new StartProcessInfo();
				spi.setBusinessId(newBankId);
				spi.setPromoter(ContextHolder.getLoginUserName());
				spi.setCompleteStartTask(true);
				
				NewBank newBank = this.bankDao.get(newBankId, NewBank.class);
				params.put("title", newBank.getNewBankTitle());
				spi.setVariables(params);
				ProcessInstance pi=this.pc.startProcessByName("新开业银行辅导", spi);
				final Opinion o = new Opinion();
				o.setBusKey(newBankId);
				o.setBusTable(GetTableUtils.getTablename(NewBank.class));
				o.setOpinion("提交申请");
				o.setProcessInstanceId(pi.getId());
				o.setProcessName("新开业银行辅导");
				o.setTaskName("申请任务");
				o.setUsername(ContextHolder.getLoginUserName());
				o.setCname(ContextHolder.getLoginUser().getCname());
				o.setDeptId(ContextHolder.getLoginUser().getDepts().get(0).getId());
				o.setDeptName(ContextHolder.getLoginUser().getDepts().get(0).getName());
				this.coreHibernateDao.save(o);
			}
			NewBank newBank = this.bankDao.get(newBankId, NewBank.class);
			newBank.setState(10);
			this.bankDao.update(newBank);
		}
		
		@Expose
		public void cancelApply(Map<String, Object> params) throws Exception {
			String newBankId = (String) params.get("newBankId");
			String taskId = (String) params.get("taskId");
			String opinion = (String) params.get("opinion");
			long ltaskId = Long.parseLong(taskId);
			Task task = this.tc.getTask(ltaskId);
			final Opinion o = new Opinion();
			o.setBusKey(newBankId);
			o.setBusTable(GetTableUtils.getTablename(NewBank.class));
			o.setOpinion(opinion);
			o.setProcessInstanceId(task.getProcessInstanceId());
			o.setProcessName("新开业银行辅导");
			o.setTaskId(ltaskId);
			o.setTaskName(task.getTaskName());
			o.setUsername(ContextHolder.getLoginUserName());
			o.setCname(ContextHolder.getLoginUser().getCname());
			o.setDeptId(ContextHolder.getLoginUser().getDepts().get(0).getId());
			o.setDeptName(ContextHolder.getLoginUser().getDepts().get(0).getName());
			this.coreHibernateDao.save(o);	
			this.tc.forward(ltaskId, "结束");
			
			NewBank newBank = this.bankDao.get(newBankId, NewBank.class);
			newBank.setState(20);
			this.bankDao.update(newBank);
		}
		

		@Expose
		@Transactional
		public void CZSH(Map<String, Object> params) throws Exception {
			String newBankId = (String) params.get("newBankId");
			String taskId = (String) params.get("taskId");
			String opinion = (String) params.get("opinion");
			boolean isagree = (boolean) params.get("isagree");
			Map<String, Object> variables=new HashMap<String, Object>();
			variables.put("agree", isagree ? 1:0);
			this.completeTask(newBankId, taskId, opinion, variables);
		}
		

		@Expose
		@Transactional
		public void FDCB(Map<String, Object> params) throws Exception {
			final String trainDeptId = (String) params.get("trainDeptId");
			String taskId = (String) params.get("taskId");
			Integer opinion = (Integer) params.get("opinion");
			String opinionstr = (String) params.get("opinionstr");
			TrainDept trainDept=this.bankDao.get(trainDeptId, TrainDept.class);
			trainDept.setOpinion(opinion);
			trainDept.setTrainCz(ContextHolder.getLoginUserName());
			trainDept.setTrainCzCname(ContextHolder.getLoginUser().getCname());
			this.bankDao.update(trainDept);
			if(opinion==2){
				this.bankDao.doInHibernateSession(new ISessionCallback<Integer>() {
					@Override
					public Integer doInSession(Session session) {
						// TODO Auto-generated method stub
						Query query=session.createQuery("delete from "+BackTrain.class.getName()+" where trainId=:trainId");
						query.setString("trainId", trainDeptId);
						return query.executeUpdate();
					}
				});
			}
			this.completeTask(trainDept.getBankId(), taskId, opinionstr, null);
		}
		
		@Expose
		@Transactional
		public void CBQR(Map<String, Object> params) throws Exception {
			String newBankId = (String) params.get("newBankId");
			String taskId = (String) params.get("taskId");
			String opinion = (String) params.get("opinion");
			Integer isagree = (Integer) params.get("isagree");
			Map<String, Object> variables=new HashMap<String, Object>();
			variables.put("agree", isagree);
			this.completeTask(newBankId, taskId, opinion, variables);
		}
		
		@Expose
		@Transactional
		public void FDFK(Map<String, Object> params) throws Exception {
			String taskId = (String) params.get("taskId");
			String newBankId = (String) params.get("newBankId");
			this.completeTask(newBankId, taskId, "操作员反馈处理情况", null);
		}
		
		@Expose
		@Transactional
		public void CZQR(Map<String, Object> params) throws Exception {
			String newBankId = (String) params.get("newBankId");
			String taskId = (String) params.get("taskId");
			String opinion = (String) params.get("opinion");
			boolean isagree = (boolean) params.get("isagree");
			Map<String, Object> variables=new HashMap<String, Object>();
			variables.put("agree", isagree ? 1:0);
			this.completeTask(newBankId, taskId, opinion, variables);
		}
		
}
